#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
高德地图 MCP (Model Context Protocol) 服务
提供地图搜索、路线规划、天气查询等功能
"""

import json
import time
import requests
from typing import Dict, List, Any, Optional
import threading
import queue


class AmapMCPService:
    """高德地图MCP服务客户端 - SSE模式"""
    
    def __init__(self, api_key: str, base_url: str = "https://mcp.amap.com"):
        """
        初始化MCP服务
        
        Args:
            api_key: 高德地图API Key
            base_url: MCP服务基础URL
        """
        self.api_key = api_key
        self.base_url = base_url
        self.sse_endpoint = f"{base_url}/sse"
        self.session = requests.Session()
        self.connected = False
        self.tools_cache = None
        self.message_id = 0
        self._lock = threading.Lock()
        
        print(f"📍 初始化高德地图MCP服务 (API Key: {api_key[:8]}...)")
    
    def _generate_message_id(self) -> int:
        """生成唯一的消息ID"""
        with self._lock:
            self.message_id += 1
            return self.message_id
    
    def _send_sse_request(self, method: str, params: Optional[Dict] = None) -> Dict[str, Any]:
        """
        通过SSE发送MCP协议请求
        
        Args:
            method: MCP方法名（如 tools/list, tools/call）
            params: 方法参数
            
        Returns:
            响应数据字典
        """
        try:
            # 构建MCP协议消息
            message = {
                "jsonrpc": "2.0",
                "id": self._generate_message_id(),
                "method": method
            }
            
            if params:
                message["params"] = params
            
            print(f"📤 发送MCP请求: {method}")
            print(f"   参数: {json.dumps(params, ensure_ascii=False) if params else 'None'}")
            
            # 构建完整URL（包含method参数）
            url = f"{self.sse_endpoint}?key={self.api_key}&method={method}"
            
            # 打印调试信息
            print(f"   URL: {url[:50]}...")  # 只显示前50个字符
            
            # 根据是否有参数决定使用GET还是POST
            headers = {
                'Accept': 'text/event-stream',
                'User-Agent': 'Python-MCP-Client/1.0'
            }
            
            if params:
                # 有参数时使用POST
                headers['Content-Type'] = 'application/json'
                response = self.session.post(
                    url,
                    json=message,
                    headers=headers,
                    stream=True,
                    timeout=30
                )
            else:
                # 无参数时使用GET（tools/list通常是GET）
                response = self.session.get(
                    url,
                    headers=headers,
                    stream=True,
                    timeout=30
                )
            
            print(f"   响应状态: HTTP {response.status_code}")
            
            if response.status_code != 200:
                # 尝试读取错误信息
                error_text = response.text[:200] if hasattr(response, 'text') else ''
                raise Exception(f"SSE请求失败: HTTP {response.status_code}\n   错误信息: {error_text}")
            
            # 解析SSE响应
            result = self._parse_sse_response(response)
            self.connected = True
            
            return result
            
        except requests.exceptions.RequestException as e:
            print(f"❌ SSE请求异常: {str(e)}")
            self.connected = False
            raise Exception(f"网络请求失败: {str(e)}")
        except Exception as e:
            print(f"❌ MCP请求失败: {str(e)}")
            raise
    
    def _parse_sse_response(self, response: requests.Response) -> Dict[str, Any]:
        """
        解析SSE流式响应
        
        Args:
            response: requests响应对象
            
        Returns:
            解析后的结果
        """
        result_data = None
        
        try:
            for line in response.iter_lines(decode_unicode=True):
                if not line:
                    continue
                
                # SSE格式: "data: {...}"
                if line.startswith('data: '):
                    data_str = line[6:]  # 去掉 "data: " 前缀
                    
                    # 跳过心跳消息
                    if data_str.strip() == '[DONE]' or data_str.strip() == '':
                        continue
                    
                    try:
                        data = json.loads(data_str)
                        
                        # MCP协议响应格式
                        if 'result' in data:
                            result_data = data['result']
                        elif 'error' in data:
                            error = data['error']
                            raise Exception(f"MCP错误: {error.get('message', str(error))}")
                        
                    except json.JSONDecodeError:
                        continue
            
            if result_data is None:
                raise Exception("未收到有效的MCP响应")
            
            return result_data
            
        except Exception as e:
            print(f"❌ 解析SSE响应失败: {str(e)}")
            raise
    
    def list_tools(self) -> List[Dict[str, Any]]:
        """
        列出所有可用的MCP工具
        
        Returns:
            工具列表，每个工具包含name, description, inputSchema等信息
        """
        try:
            if self.tools_cache:
                return self.tools_cache
            
            print("🔍 正在获取可用工具列表...")
            result = self._send_sse_request("tools/list")
            
            if 'tools' in result:
                self.tools_cache = result['tools']
                print(f"✅ 获取到 {len(self.tools_cache)} 个工具")
                
                # 打印工具列表
                for tool in self.tools_cache:
                    print(f"   • {tool.get('name')}: {tool.get('description', 'N/A')}")
                
                return self.tools_cache
            else:
                raise Exception("响应中未包含工具列表")
                
        except Exception as e:
            print(f"❌ 获取工具列表失败: {str(e)}")
            return []
    
    def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
        """
        调用指定的MCP工具
        
        Args:
            tool_name: 工具名称（如 maps_weather, maps_search等）
            arguments: 工具参数
            
        Returns:
            工具执行结果
        """
        try:
            print(f"\n🛠️  调用工具: {tool_name}")
            print(f"   参数: {json.dumps(arguments, ensure_ascii=False)}")
            
            params = {
                "name": tool_name,
                "arguments": arguments
            }
            
            result = self._send_sse_request("tools/call", params)
            
            print(f"✅ 工具调用成功")
            
            # 解析结果
            if 'content' in result:
                content = result['content']
                if isinstance(content, list) and len(content) > 0:
                    first_content = content[0]
                    if 'text' in first_content:
                        # 尝试解析为JSON
                        try:
                            parsed_result = json.loads(first_content['text'])
                            return {
                                'success': True,
                                'data': parsed_result,
                                'raw': result
                            }
                        except json.JSONDecodeError:
                            return {
                                'success': True,
                                'data': first_content['text'],
                                'raw': result
                            }
            
            return {
                'success': True,
                'data': result,
                'raw': result
            }
            
        except Exception as e:
            print(f"❌ 工具调用失败: {str(e)}")
            return {
                'success': False,
                'error': str(e),
                'data': None
            }
    
    # ========== 便捷方法：封装常用功能 ==========
    
    def search_poi(self, keywords: str, city: Optional[str] = None) -> Dict[str, Any]:
        """
        搜索POI（地点）
        
        Args:
            keywords: 搜索关键词
            city: 城市名称（可选）
            
        Returns:
            搜索结果
        """
        args = {"keywords": keywords}
        if city:
            args["city"] = city
        
        return self.call_tool("maps_search", args)
    
    def get_weather(self, city: str) -> Dict[str, Any]:
        """
        查询天气
        
        Args:
            city: 城市名称
            
        Returns:
            天气信息
        """
        return self.call_tool("maps_weather", {"city": city})
    
    def plan_route(
        self,
        origin: str,
        destination: str,
        mode: str = "driving",
        city: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        规划路线
        
        Args:
            origin: 起点
            destination: 终点
            mode: 出行方式（driving/walking/transit/riding）
            city: 城市（可选）
            
        Returns:
            路线规划结果
        """
        args = {
            "origin": origin,
            "destination": destination,
            "mode": mode
        }
        if city:
            args["city"] = city
        
        return self.call_tool("maps_direction", args)
    
    def geocode(self, address: str, city: Optional[str] = None) -> Dict[str, Any]:
        """
        地理编码（地址转坐标）
        
        Args:
            address: 地址
            city: 城市（可选）
            
        Returns:
            坐标信息
        """
        args = {"address": address}
        if city:
            args["city"] = city
        
        return self.call_tool("maps_geocode", args)
    
    def reverse_geocode(self, location: str) -> Dict[str, Any]:
        """
        逆地理编码（坐标转地址）
        
        Args:
            location: 经纬度（格式：经度,纬度）
            
        Returns:
            地址信息
        """
        return self.call_tool("maps_regeo", {"location": location})
    
    def get_status(self) -> Dict[str, Any]:
        """获取服务状态"""
        return {
            'connected': self.connected,
            'api_key_configured': bool(self.api_key),
            'tools_count': len(self.tools_cache) if self.tools_cache else 0,
            'base_url': self.base_url
        }
    
    def disconnect(self):
        """断开连接"""
        try:
            self.session.close()
            self.connected = False
            print("🔌 已断开MCP连接")
        except Exception as e:
            print(f"⚠️  断开连接时出错: {str(e)}")


# ========== 便捷函数：快速使用 ==========

def create_amap_service(api_key: str) -> AmapMCPService:
    """
    创建高德地图MCP服务实例
    
    Args:
        api_key: 高德地图API Key
        
    Returns:
        AmapMCPService实例
    """
    service = AmapMCPService(api_key)
    # 自动获取工具列表
    service.list_tools()
    return service

